'use strict';

const chalk = require('chalk');
const git = require('./utils/git');

const DOCS_LABEL = 'Documentation: needs merge to stable';

// FOR DOCS
// get all issues with label
// ensure all have pull_request
//   FAIL: log issues that aren't prs
// fetch each pr, (issues.pull_request.url)
// sort each by merged_at
// git cherry-pick -x sha || git cherry-pick -x -m1 sha
//   (or use API to look up number of parents, 2 = use -m1)
// track progress. on fail, pause and force user to handle manually, continue? prompt
// git push
// update labels on each PR
//   ALT: dump link to
//        https://github.com/facebook/react/issues?q=label%3A%22Documentation%3A+needs+merge+to+stable%22+is%3Aclosed
//        and say manual step to remove label

module.exports = function(vorpal, app) {
  vorpal
    .command('docs-prs')
    .description(
      'Get list of documentation pull requests that need to be merged to the stable branch'
    )
    .action(function(args, actionCB) {
      const branch = git.getBranch(app);
      if (!branch.match(/-stable$/)) {
        this.log(chalk.red('Aborting...'));
        this.log(
          `You need to be on the latest stable branch in the React repo ` +
            `to execute this command.\nYou are currently in ${branch}.`
        );
        actionCB();
        return;
      }

      const query = {
        labels: [DOCS_LABEL].join(), // github-api doesn't join automatically
        state: 'closed',
      };

      app.ghissues.listIssues(query, (err, body) => {
        app.writeTo('issues.json', body);
        // console.log(body);
        // fs.writeFileSync('body.json', JSON.stringify(body, null, 2));
        // fs.writeFileSync('headers.json', JSON.stringify(headers, null, 2));
        // const prs = require('./body');

        // This API *could* return issues that aren't pull requests, so filter out
        // issues that don't have pull_request set.
        const pulls = body.filter(issue => issue.pull_request);

        // We don't enough data about the pull request (merge sha or merge time) so we
        // need to fetch more. We'll use promises so we don't have to count completions.
        const pullPromises = pulls.map(pr => {
          return new Promise((resolve, reject) => {
            app.ghrepo.getPullRequest(pr.number, (err, body) => {
              if (err) {
                reject(err);
              }

              app.writeTo(`pr-${pr.number}.json`, body);
              // We want to track the original issue as well since it has the
              // label information.
              const richPull = body;
              richPull.__originalIssue = pr;
              resolve(richPull);
            });
          });
        });
        Promise.all(pullPromises).then(richPulls => {
          richPulls.forEach(pr => {
            // Convert merged_at to real Date for sorting
            pr.merged_at_date = new Date(pr.merged_at);
          });

          richPulls = richPulls.sort(
            (a, b) => a.merged_at_date - b.merged_at_date
          );

          this.log(`Found ${chalk.bold(richPulls.length)} pull requests:`);
          richPulls.forEach(pr => {
            this.log(`${pr.html_url}: ${chalk.bold(pr.title)}`);
          });

          this.prompt(
            {
              name: 'merge',
              type: 'confirm',
              message: `Merge these ${richPulls.length} pull requests?`,
            },
            res => {
              if (res.merge) {
                richPulls.forEach(pr => {
                  git.cherryPickMerge(app, pr.merge_commit_sha);
                });

                this.prompt(
                  {
                    name: 'push',
                    type: 'confirm',
                    message: 'Push these commits upstream?',
                  },
                  res => {
                    if (res.push) {
                      git.push(app);
                      this.log(
                        `Pushed upstream! Removing "${DOCS_LABEL}" label from pull requests.`
                      );
                    }

                    // TODO: actually test this
                    var removeLabelsPromises = richPulls.map(pr => {
                      return new Promise((resolve, reject) => {
                        const updatedLabels = pr.__originalIssue.labels
                          .filter(label => label.name !== DOCS_LABEL)
                          .map(label => label.name);
                        app.ghissues.editIssue(
                          pr.number,
                          {labels: updatedLabels},
                          (err, body) => {
                            if (err) {
                              reject(err);
                            } else {
                              resolve(pr);
                            }
                          }
                        );
                      });
                    });

                    Promise.all(removeLabelsPromises).then(() => {
                      this.log('Done!');
                      actionCB();
                    });
                  }
                );
              } else {
                actionCB();
              }
            }
          );
        });
      });
    });
};
